# coding=utf-8
import string
import copy
from django.conf import settings
from lib.push.youmenpush import ios_pusher, android_pusher
import random
from collections import defaultdict
from itertools import chain
from django.core.cache import cache
import numpy as np
from celery import shared_task, group
from django.contrib.contenttypes.models import ContentType
from django.db import transaction, connection
from lib.common import CacheKeys
from django.db.models import Sum, F, Q, Count, Avg
import datetime
from project.settings_common import USER_TYPE
from services.datamodel.share import stats_logger
import json, traceback, gc
from services.datamodel.student.models import (mm_Student, mm_StudentCapital, mm_StudentTeam)
from services.datamodel.order.models import (mm_Order)
from services.datamodel.history.models import (mm_HistoryCache)
from services.datamodel.utils import Utils
from django.db.models.functions import Coalesce
from apps.student.share import app_logger


def queryset_iterator(queryset, chunksize=1000):
    '''''
    Iterate over a Django Queryset ordered by the primary key

    This method loads a maximum of chunksize (default: 1000) rows in it's
    memory at the same time while django normally would load all rows in it's
    memory. Using the iterator() method only causes it to not preload all the
    classes.

    Note that the implementation of the iterator does not support ordered query sets.
    '''

    if queryset.count() == 0:
        return

    pk = 0
    last_pk = queryset.order_by('-pk')[0].pk
    queryset = queryset.order_by('pk')
    while pk < last_pk:
        for row in queryset.filter(pk__gt=pk)[:chunksize]:
            pk = row.pk
            yield row
        gc.collect()


# 需求: 周期性 统计题目的正确错误次数、平均答题时间  case - A1
#  需求: 老师自己发布的所有任务里每道题目  在指定时间段内 自己学生 做的 对错次数 平均答题时间  （A4）

class PeriodStats:
    # 一次采集处理源数据最大记录条数
    SOURCE_RECORD_COLLECT_LIMIT = 200000

    def __init__(self):
        # TOTAL_QUESTION_TABLE             keys are submitDate|subjectid|questionType|questionId
        # TOTAL_QUESTION_FOR_TEACHER_TABLE keys are submitDate|subjectid|teacherUserId|questionType|questionId
        # values are total_number|correct number|wrong number|total time
        self.TOTAL_QUESTION_TABLE = {}
        self.TOTAL_QUESTION_FOR_TEACHER_TABLE = {}

        self.taskexam_laststats_to_record = 0
        self.tasklesson_laststats_to_record = 0

        self.psCtrl = None

    def _agent_datas_statistics(self):
        pass


@shared_task(name='peroid_statsQuestionAnswersAlsoForTeacher', queue='cpubound', ignore_result=True)
def peroid_statsQuestionAnswersAlsoForTeacher():
    stats_logger.critical('<==== peroid_statsQuestionAnswersAlsoForTeacher *** begin ====>')

    ps = PeriodStats()
    # ps.statsQuestionAnswersAlsoForTeacher()

    stats_logger.critical('<==== peroid_statsQuestionAnswersAlsoForTeacher *** end ====>')


@shared_task(name='statisticsAgentdatas', queue='cpubound', ignore_result=True)
def statisticsAgentdatas():
    """
     凌晨3点执行
     python manage.py shell
     from services.asyntask import idle_tasks
     idle_tasks.statisticsAgentdatas()
    :return:
    """
    stats_logger.critical('<==== statisticsAgentdatas *** begin ====>')
    #  created_at__range=[start_date, end_date]
    yesterday = Utils.getYesterday()
    day = datetime.datetime.now().day
    month = datetime.datetime.now().month
    year = datetime.datetime.now().year
    if day == 1:
        month -= 1
        if month == 1:
            year -= 1
    month_start, month_end = Utils.get_month_start_and_end_date(year, month)
    query_day = Q(created_at__gte=str(yesterday) + ' 00:00:00', created_at__lte=str(yesterday) + ' 23:59:59')
    query_month = Q(created_at__gte=month_start, created_at__lte=month_end)
    result = queryset_iterator(mm_Student.filter(~Q(level=0)))
    try:
        for v in result:
            direct_daili_totall_user = CacheKeys.DIRECT_DAILI_TOTALL_USER % (str(v.id))  # 直接代理
            indirect_daili_totall_user = CacheKeys.INDIRECT_DAILI_TOTALL_USER % (str(v.id))  # 间接代理
            direct_for_vip_user = CacheKeys.DIRECT_FOR_VIP_USER % (str(v.id))  # 直接发展vip
            direct = mm_StudentTeam.filter(query_day).filter(parent_id=v.id, status=2, level=1).count()
            direct_user = cache.get(direct_daili_totall_user)
            # 更新数据库
            mm_HistoryCache.add_data(name="代理-直接开户代理", day=yesterday, cache_key=direct_daili_totall_user,
                                     cache_value=direct_user + direct if direct_user else 0)
            if direct_user:
                cache.incr(direct_daili_totall_user, direct)
            else:
                cache.set(direct_daili_totall_user, direct, None)
            indirect = mm_StudentTeam.filter(query_day).filter(parent_id=v.id, status=2).filter(~Q(level=1)).count()
            indirect_user = cache.get(indirect_daili_totall_user)
            # 更新数据库
            mm_HistoryCache.add_data(name="代理-间接开户代理", day=yesterday, cache_key=indirect_daili_totall_user,
                                     cache_value=indirect_user + indirect if indirect_user else 0)
            if indirect_user:
                cache.incr(indirect_daili_totall_user, indirect)
            else:
                cache.set(indirect_daili_totall_user, indirect, None)
            # 统计vip
            direct_vip = mm_StudentTeam.filter(query_day).filter(parent_id=v.id, status=1, level=1).count()
            direct_vip_user = cache.get(direct_for_vip_user)
            # 更新数据库
            mm_HistoryCache.add_data(name="代理-直接发展vip数", day=yesterday, cache_key=direct_for_vip_user,
                                     cache_value=direct_vip_user + direct_vip if direct_vip_user else 0)
            if direct_vip_user:
                cache.incr(direct_daili_totall_user, direct_vip)
            else:
                cache.set(direct_daili_totall_user, direct_vip, None)
            # 订单总数据
            quer = mm_Order.filter(agent_id=v.id, goods_type__in=[1, 2, 3], status=2)
            quer_capital = mm_StudentCapital.filter(seller_student_id=v.id, goods_type__in=[1, 2, 3], types__in=[1, 2, 3])
            order_total = quer.filter(query_month).count()
            total_money = quer_capital.aggregate(total=Coalesce(Sum("momey"), 0))  # 总收益--399
            order_money_total = CacheKeys.ORDER_MONEY_TOTAL % (str(v.id))  # 代理销售总额
            cache.set(order_money_total, total_money['total'], None)
            # 更新数据库
            mm_HistoryCache.add_data(name="代理销售总额", day=yesterday, cache_key=order_money_total,
                                     cache_value=total_money['total'])
            # 订单月份数据(当月
            month_data = quer_capital.filter(query_month).aggregate(total=Coalesce(Sum("momey"), 0))
            money_month_total = CacheKeys.MONEY_MONTH_TOTAL % (str(v.id), str(month))
            # old_total = cache.get(money_month_total)
            cache.set(money_month_total, month_data['total'], None)  # 代理每月的销售总额度
            # 更新数据库
            mm_HistoryCache.add_data(name="代理每月的销售额度", day=yesterday, cache_key=money_month_total,
                                     cache_value=month_data['total'])
            order_year = CacheKeys.ORDER_YEAR_DETAIL % (str(v.id), str(year))
            order_year_detail_json = cache.get(order_year)  # 获取年度订单详情
            if order_year_detail_json:
                dict_detail = json.loads(order_year_detail_json)
                dict_detail[str(month)] = {'total_num': order_total, 'total_money': month_data['total'], 'month': month}
                json_dict = json.dumps(dict_detail)
                cache.set(order_year, json_dict, None)
                # 更新数据库
                mm_HistoryCache.add_data(name="代理每年每月的销售订单", day=yesterday, cache_key=order_year,
                                         cache_value=json_dict)
            else:
                json_data = json.dumps({month: {'total_num': order_total, 'total_money': month_data['total'],
                                                'month': month}})
                cache.set(order_year, json_data, None)
                # 更新数据库
                mm_HistoryCache.add_data(name="代理每年每月的销售订单", day=yesterday, cache_key=order_year,
                                         cache_value=json_data)
            #  冻结资金
            frozen_total = quer_capital.filter(status=0).aggregate(total=Coalesce(Sum("momey"), 0))
            frozen_total_key = CacheKeys.FROZEN_TOTAL % (str(v.id))
            # old_frozen_total = cache.get(frozen_total_key)
            cache.set(frozen_total_key, frozen_total['total'], None)  # 总的冻结资金
            # 更新数据库
            mm_HistoryCache.add_data(name="冻结资金", day=yesterday, cache_key=frozen_total_key,
                                     cache_value=frozen_total['total'])
    except Exception as e:
        err = traceback.format_exc()
        app_logger.error(err)
    stats_logger.critical('<==== statisticsAgentdatas *** end ====>')


# @shared_task(name='statisticsUser', queue='cpubound', ignore_result=True)
def statisticsUser():
    result = queryset_iterator(mm_Student.filter(level__in=[0, 1, 2, 3, 4, 5, 6]))
    for v in result:
        print(v.id)
